#include "Position.h"

#include <cstring>

#include "MoveTreeNode.h"
#include "Square.h"
#include "Piece.h"
#include "Pawn.h"
#include "Knight.h"
#include "Bishop.h"
#include "Rook.h"
#include "Queen.h"
#include "King.h"

using namespace Rorn::Chess::TheCorruptRook;

Position::Position(void)
{
	Reset();
}


Position::~Position(void)
{
}

void Position::Reset()
{
	boardState_[0][0] = Piece::MyRook;
	boardState_[0][1] = Piece::MyKnight;
	boardState_[0][2] = Piece::MyBishop;
	boardState_[0][3] = Piece::MyQueen;
	boardState_[0][4] = Piece::MyKing;
	boardState_[0][5] = Piece::MyBishop;
	boardState_[0][6] = Piece::MyKnight;
	boardState_[0][7] = Piece::MyRook;
	boardState_[1][0] = Piece::MyPawn;
	boardState_[1][1] = Piece::MyPawn;
	boardState_[1][2] = Piece::MyPawn;
	boardState_[1][3] = Piece::MyPawn;
	boardState_[1][4] = Piece::MyPawn;
	boardState_[1][5] = Piece::MyPawn;
	boardState_[1][6] = Piece::MyPawn;
	boardState_[1][7] = Piece::MyPawn;
	memset(boardState_ + 2, 0, 32);
	boardState_[6][0] = Piece::TheirPawn;
	boardState_[6][1] = Piece::TheirPawn;
	boardState_[6][2] = Piece::TheirPawn;
	boardState_[6][3] = Piece::TheirPawn;
	boardState_[6][4] = Piece::TheirPawn;
	boardState_[6][5] = Piece::TheirPawn;
	boardState_[6][6] = Piece::TheirPawn;
	boardState_[6][7] = Piece::TheirPawn;
	boardState_[7][0] = Piece::TheirRook;
	boardState_[7][1] = Piece::TheirKnight;
	boardState_[7][2] = Piece::TheirBishop;
	boardState_[7][3] = Piece::TheirQueen;
	boardState_[7][4] = Piece::TheirKing;
	boardState_[7][5] = Piece::TheirBishop;
	boardState_[7][6] = Piece::TheirKnight;
	boardState_[7][7] = Piece::TheirRook;
}

void Position::GetLegalMoves(Player::Type player, std::vector<MoveTreeNode>& legalMoves, int depth) const
{
	// enumerate the available moves
	for(int rank = 0 ; rank < 8 ; ++rank)
	{
		for(int file = 0 ; file < 8 ; ++file)
		{
			Square startSquare(rank, file);

			if(GetPiece(player, startSquare) == Piece::MyPawn)
			{
				Pawn::GetLegalMoves(*this, player, startSquare, legalMoves, depth);
			}
			else if(GetPiece(player, startSquare) == Piece::MyKnight)
			{
				Knight::GetLegalMoves(*this, player, startSquare, legalMoves, depth);
			}
			else if(GetPiece(player, startSquare) == Piece::MyBishop)
			{
				Bishop::GetLegalMoves(*this, player, startSquare, legalMoves, depth);
			}
			else if(GetPiece(player, startSquare) == Piece::MyRook)
			{
				Rook::GetLegalMoves(*this, player, startSquare, legalMoves, depth);
			}
			else if(GetPiece(player, startSquare) == Piece::MyQueen)
			{
				Queen::GetLegalMoves(*this, player, startSquare, legalMoves, depth);
			}
			else if(GetPiece(player, startSquare) == Piece::MyKing)
			{
				King::GetLegalMoves(*this, player, startSquare, legalMoves, depth);
			}

			// TODO - think about en-passant and check
		}
	}
}

int Position::GetPiece(Player::Type player, const Square& square) const
{
	if(player == Player::White)
	{
		return boardState_[square.GetRank()][square.GetFile()];
	}
	else
	{
		return -(boardState_[7 - square.GetRank()][7 - square.GetFile()]);
	}
}

double Position::CalculateScore(Player::Type player) const
{
	if(player == Player::White)
	{
		return CalculateScoreOnePlayer(Player::White) - CalculateScoreOnePlayer(Player::Black);
	}
	else
	{
		return CalculateScoreOnePlayer(Player::Black) - CalculateScoreOnePlayer(Player::White);
	}
}

void Position::MovePiece(Player::Type player, const Square& startSquare, const Square& endSquare)
{
	if(player == Player::White)
	{
		boardState_[endSquare.GetRank()][endSquare.GetFile()] = boardState_[startSquare.GetRank()][startSquare.GetFile()];
		boardState_[startSquare.GetRank()][startSquare.GetFile()] = 0;
	}
	else
	{
		boardState_[7 - endSquare.GetRank()][7 - endSquare.GetFile()] = boardState_[7 - startSquare.GetRank()][7 - startSquare.GetFile()];
		boardState_[7 - startSquare.GetRank()][7 - startSquare.GetFile()] = 0;
	}
}

double Position::CalculateScoreOnePlayer(Player::Type player) const
{
	double score = 0;

	for(int rank = 0 ; rank < 8 ; ++rank)
	{
		for(int file = 0 ; file < 8 ; ++file)
		{
			Square startSquare(rank, file);

			if(GetPiece(player, startSquare) == Piece::MyPawn)
			{
				score += Pawn::CalculateScore(*this, player, startSquare);
			}
			else if(GetPiece(player, startSquare) == Piece::MyKnight)
			{
				score += Knight::CalculateScore(*this, player, startSquare);
			}
			else if(GetPiece(player, startSquare) == Piece::MyBishop)
			{
				score += Bishop::CalculateScore(*this, player, startSquare);
			}
			else if(GetPiece(player, startSquare) == Piece::MyRook)
			{
				score += Rook::CalculateScore(*this, player, startSquare);
			}
			else if(GetPiece(player, startSquare) == Piece::MyQueen)
			{
				score += Queen::CalculateScore(*this, player, startSquare);
			}
			else if(GetPiece(player, startSquare) == Piece::MyKing)
			{
				score += King::CalculateScore(*this, player, startSquare);
			}
		}
	}

	return score;
}